#ifndef TRANSFORMERCONTENTPORTLISTEN_HPP_3
#define TRANSFORMERCONTENTPORTLISTEN_HPP_3

#include "logger.hpp"
#include "transContentDefine.h"
#include "transContentErrorCode.h"
#include "transContentDispatcher.hpp"
#include "transContentAssistent.hpp"
#include "transContentIDispatcherResponse.hpp"
#include "transContentIRemove.hpp"


///////////////////////////////////////////////////////////////////////////////
/// how accept work:
/// 1. accept get the connect request
/// 2. accept instance response method to extract the endpoint information
/// 3. the port manager call acceptInstance method to get the endPoint information
/// 4. the port manager create a new stream port record
/// 5. the port manager call the stream port record method init(block)
/// 6. the port manager call the accept instance getResult method to test timeout, if timed out, remove the stream record
/// 6. the port manager call the accept instance finished method
/// 7. accept finished
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////
/// connect protocol content format(out)
///  name | total len | target | flag | length | mainCode | subCode | remotePort| local port | local addr |
///  len  |    2      |   8    |   1  |    2   |     1    |    1    |     4     |     4      |     8      |
/// offset|    0      |   2    |   10 |   11   |     13   |    14   |    15     |     19     |     23     |
///
/// accept protocol content format(in)
///  name |  mainCode | subCode | localPort | remote port | remote addr |
///   len |      1    |    1    |    4      |    4        |    8        |
/// offset|      0    |    1    |    2      |    6        |    10       |
///
/// accept ack protocol content format(out)
///  name | total len | target | flag |  length | mainCode | subCode | remotePort | result | local port | local addr |
///  len  |    2      |   8    |  1   |    2    |     1    |    1    |     4      |    1   |      4     |     8      |
/// offset|    0      |   2    |  10  |    11   |    13    |    14   |    15      |    19  |      20    |     24     |
///
/// stream start protocol content format(out) both side after create sucessfully stream instance will send this packet
///	 name | total len | target | flag | length | mainCode | subCode | remotePort | local port | local addr | result |buffer size | stream id |
///  len  |    2      |   8    |   1  |   2    |    1     |    1    |     4      |    4       |    8       |   1    |     1      |     4     |
/// offset|    0      |    2   |   10 |  11    |     13   |   14    |    15      |    19      |    23      |   31   |     32     |     33    |
///
/// stream start protocol do not need reply
////////////////////////////////////////////////////////////////////////////
class TransContentPortListen: public transContentIDispResponse, public transContentIRemove{
	private:
		int localPort;
		int timeout;
		int leftAllowedCount;
		int totalAllowedCount;
		int canBeRemoved;
		/// 0: failed, 1. sucess, 2. stream create failed, 3. timedout
		int acceptResult;
		/// 0: not start, 1. accepting, 2. accepting-dealing
		int acceptState;
		/// used as return value
		vroute_t streamVid;
		acceptSyncCallback callback;
		pthread_cond_t waitCond;
		pthread_mutex_t waitMutex;
		ConnectPeer mPeer;
	public:

		TransContentPortListen():localPort(0), timeout(INT_MAX), leftAllowedCount(0), totalAllowedCount(0), canBeRemoved(0),acceptResult(0), acceptState(0), streamVid(-1), callback(NULL), waitCond(PTHREAD_COND_INITIALIZER), waitMutex(PTHREAD_MUTEX_INITIALIZER){
			debug_enter();
		}
		virtual ~TransContentPortListen(){
			debug_enter();
		};

		int getLocalPort() const{
			return this->localPort;
		}

		void setLocalPort(int port){
			this->localPort = port;
		}

		ConnectPeer getPeer() const{
			return mPeer;
		}

		int canRemoved() const{
			//return this->canBeRemoved;
			return 0; // now accept not really support listen count,
		}

		/// vid < 0, error, else sucess
		void setStreamVid(vroute_t vid){
			this->streamVid = vid;
		}

		vroute_t getStreamVid() const{
			return streamVid;
		}

		int listen(int count){
			this->totalAllowedCount = count;
		}

		void setTimeout(int timeout){
			this->timeout = timeout;
		}

		int getTimeout() const {
			return this->timeout;
		}

		void setAcceptCallback(acceptSyncCallback ascb){
			this->callback = ascb;
		}
		
		acceptSyncCallback getAcceptCallback() const {
			return this->callback;
		}

		int getLeftAccpetAbleCount() const {
			return leftAllowedCount;
		}

		int getTotalAcceptAbleCount() const {
			return totalAllowedCount;
		}

		vroute_t accept();

		int response(char* content, int index);

	private:
		void* finishRoute(void* p);

		void finishedCallback();

		/// respinse then the accept port is busy
		void acceptACK(ConnectPeer* remotePeer, int result);
};
#endif //TRANSFORMERCONTENTPORTLISTEN_HPP_3
